# Copyright (c) 2009 Barry Schwartz
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
# 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

import os
import shutil
import fileinput
import subprocess
from SCons.Action import ActionFactory
from SCons.Defaults import Copy

def in_dir(d, m):
    return os.path.join(d, m)

def making_native_code(env):
    return env['OCAML_COMPILER'] in ('ocamlopt', 'opt')

def get_library_extension(env):
    if making_native_code(env):
        compiler = '.cmxa'
    else:
        compiler = '.cma'
    return compiler

def get_toolchain(env):
    if env['OCAML_TOOLCHAIN'] == '':
        toolchain = []
    else:
        toolchain = ['-toolchain', env['OCAML_TOOLCHAIN']]
    return toolchain

def make_depends(env, modules, depends):
    done_dir = env['DONE_DIR']
    for d in depends:
        mod = os.path.join(done_dir, d.split('.')[-1])
        env.Depends([m + '.cmi' for m in modules], mod + '.cmi')


def order_objects(env, modules):
    args = ['-byte']
    if making_native_code(env):
        args.append('-opt')
    args += [m + '.ml' for m in modules]
    args += env['OCAMLDSORTFLAGS']
    pipe = subprocess.Popen([env['OCAMLDSORT']] + args,
                            stdout = subprocess.PIPE,
                            env    = os.environ)
    order = pipe.communicate()[0]
    return env.Split(order)


def order_objects_extless(env, modules):
    objs = order_objects(env, modules)
    obj_list = []
    for o in objs:
        (f, _) = os.path.splitext(o)
        obj_list.append(f)
    return obj_list


def find_package_dir(env, package):
    args = ['query', package]
    pipe = subprocess.Popen([env['OCAMLFIND']] + args,
                            stdout = subprocess.PIPE,
                            env    = os.environ)
    dirname = pipe.communicate()[0]
    while dirname[-1] in ' \t\n\r':
        dirname = dirname[:-1]
    return dirname


def find_package(env, package):
    dirname = find_package_dir(env, package)
    return os.path.join(dirname, package + get_library_extension(env))


def make_pack(env, pack_name, modules, depends):

    done_dir = env['DONE_DIR']

    make_depends(env, modules, depends)

    flags = env['OCAMLFLAGS'] + ['-for-pack', pack_name]
    for m in modules:
        env.OCamlInterface(m, OCAMLFLAGS = flags)
        env.OCamlObject(m, OCAMLFLAGS = flags)

    target_file = pack_name.split('.')[-1]
    target = os.path.join(done_dir, target_file)

    env.OCamlPackObj(target, modules)


def sandwiched_output_builder(source, target, env):
    program_to_run = str(source[0])
    program_input  = str(source[1])
    head_text      = str(source[2])
    tail_text      = str(source[3])

    output = str(target[0])

    f = open(output, 'w')    

    for line in fileinput.input(head_text):
        f.write(line)

    with open(program_input) as input:
        program = subprocess.Popen([program_to_run], stdin = input, stdout = subprocess.PIPE)
        for line in program.stdout:
            f.write(line)

    for line in fileinput.input(tail_text):
        f.write(line)

    f.close()
    return 0


if 'symlink' in dir(os):
    Symlink = ActionFactory((lambda dest, src: os.symlink(os.path.relpath(src, os.path.dirname(dest)), dest)),
                            (lambda dest, src: 'Symlink("%s", "%s")' % (dest, src)),
                            convert=str)
else:
    Symlink = Copy


# local variables:
# python-indent: 4
# end:
